package logger

import (
	"fmt"
)

type Level int

const (
	DEBUG Level = iota
	INFO
	WARN
	ERROR
	PANIC
	FATAL
)

func (level Level) String() string {
	switch level {
	case DEBUG:
		return "DEBUG"
	case INFO:
		return "INFO"
	case WARN:
		return "WARN"
	case ERROR:
		return "ERROR"
	case PANIC:
		return "PANIC"
	case FATAL:
		return "FATAL"
	}
	return "INFO"
}

func (level *Level) Parse(l string) error {
	switch l {
	case "DEBUG":
		*level = DEBUG
	case "INFO":
		*level = INFO
	case "WARN":
		*level = WARN
	case "ERROR":
		*level = ERROR
	case "PANIC":
		*level = PANIC
	case "FATAL":
		*level = FATAL
	default:
		return fmt.Errorf("not a valid level: %s", l)
	}
	return nil
}

type Logger interface {
	Base
	WithFields(fields map[string]interface{}) Logger
	V(level Level) StdLogger
}

type Base interface {
	Debugf(format string, args ...interface{})
	Infof(format string, args ...interface{})
	Printf(format string, args ...interface{})
	Warnf(format string, args ...interface{})
	Warningf(format string, args ...interface{})
	Errorf(format string, args ...interface{})
	Fatalf(format string, args ...interface{})
	Panicf(format string, args ...interface{})

	Debug(args ...interface{})
	Info(args ...interface{})
	Print(args ...interface{})
	Warn(args ...interface{})
	Warning(args ...interface{})
	Error(args ...interface{})
	Fatal(args ...interface{})
	Panic(args ...interface{})

	Debugln(args ...interface{})
	Infoln(args ...interface{})
	Println(args ...interface{})
	Warnln(args ...interface{})
	Warningln(args ...interface{})
	Errorln(args ...interface{})
	Fatalln(args ...interface{})
	Panicln(args ...interface{})
}

type StdLogger interface {
	Print(...interface{})
	Printf(string, ...interface{})
	Println(...interface{})
}

var globalLogger Logger

func SetupGlobalLogger(logger Logger) {
	globalLogger = logger
}

func GetLogger() Logger {
	return globalLogger
}
